package com.dd.admin.business.api;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.dd.admin.business.author.entity.Author;
import com.dd.admin.business.author.service.AuthorService;
import com.dd.admin.business.file.entity.File;
import com.dd.admin.business.file.service.FileService;
import com.dd.admin.business.follow.entity.Follow;
import com.dd.admin.business.follow.service.FollowService;
import com.dd.admin.business.note.domain.NoteDto;
import com.dd.admin.business.note.domain.NoteVo;
import com.dd.admin.business.note.entity.Note;
import com.dd.admin.business.note.service.NoteService;
import com.dd.admin.business.noteImg.entity.NoteImg;
import com.dd.admin.business.noteImg.service.NoteImgService;
import com.dd.admin.business.reply.domain.ReplyDto;
import com.dd.admin.business.reply.domain.ReplyVo;
import com.dd.admin.business.reply.entity.Reply;
import com.dd.admin.business.reply.service.ReplyService;
import com.dd.admin.business.starNotes.domain.StarNotesDto;
import com.dd.admin.business.starNotes.domain.StarNotesVo;
import com.dd.admin.business.starNotes.entity.StarNotes;
import com.dd.admin.business.starNotes.service.StarNotesService;
import com.dd.admin.business.upNotes.domain.UpNotesDto;
import com.dd.admin.business.upNotes.domain.UpNotesVo;
import com.dd.admin.business.upNotes.entity.UpNotes;
import com.dd.admin.business.upNotes.service.UpNotesService;
import com.dd.admin.business.upReplys.entity.UpReplys;
import com.dd.admin.business.upReplys.service.UpReplysService;
import com.dd.admin.common.aop.operationLog.aop.OperLog;
import com.dd.admin.common.aop.operationLog.aop.OperType;
import com.dd.admin.common.model.result.ResultBean;
import com.dd.admin.common.utils.AddressUtils;
import com.dd.admin.common.utils.CommonUtil;
import com.dd.admin.common.utils.IPUtils;
import com.dd.admin.common.utils.StringUtil;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

import static com.dd.admin.common.consts.XhsConst.TRUE;

@RestController
public class AuthApi {
    @Autowired
    AuthorService authorService;
    @Autowired
    HttpServletRequest request;
    @Autowired
    NoteService noteService;
    @Autowired
    FileService fileService;
    @Autowired
    NoteImgService noteImgService;
    @Value("${server.port}")
    String port;
    @Autowired
    UpNotesService upNotesService;
    @Autowired
    StarNotesService starNotesService;
    @Autowired
    FollowService followService;
    @Autowired
    ReplyService replyService;
    @Autowired
    UpReplysService upReplysService;

    @ApiOperation(value = "获取所有笔记")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/notes")
    @OperLog(operModule = "获取所有笔记",operType = OperType.QUERY,operDesc = "获取所有笔记")
    public ResultBean<IPage<NoteVo>> page(NoteDto noteDto) {
        String followId = String.valueOf(request.getAttribute("authorId"));
        noteDto.setFollowId(followId);
        IPage<NoteVo> pageInfo = noteService.selectNotePage(noteDto);
        return ResultBean.success(pageInfo);
    }


    @ApiOperation(value = "获取所有关注笔记")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getFollowNotes")
    @OperLog(operModule = "获取所有关注笔记",operType = OperType.QUERY,operDesc = "获取所有关注笔记")
    public ResultBean<IPage<NoteVo>> getFollowNotes() {
        String followId = String.valueOf(request.getAttribute("authorId"));
        NoteDto noteDto = new NoteDto();
        noteDto.setFollowId(followId);
        List<Follow> follows = followService.selectFollowListByFollowId(followId);

        IPage<NoteVo> pageInfo = new IPage<NoteVo>() {
            @Override
            public List<OrderItem> orders() {
                return null;
            }

            @Override
            public List<NoteVo> getRecords() {
                return null;
            }

            @Override
            public IPage<NoteVo> setRecords(List<NoteVo> records) {
                return null;
            }

            @Override
            public long getTotal() {
                return 0;
            }

            @Override
            public IPage<NoteVo> setTotal(long total) {
                return null;
            }

            @Override
            public long getSize() {
                return 0;
            }

            @Override
            public IPage<NoteVo> setSize(long size) {
                return null;
            }

            @Override
            public long getCurrent() {
                return 0;
            }

            @Override
            public IPage<NoteVo> setCurrent(long current) {
                return null;
            }
        };
        if(CollectionUtil.isNotEmpty(follows)){
            String authorIds = CommonUtil.getIds(follows, "authorId");
            noteDto.setAuthorIds(authorIds);
            pageInfo = noteService.selectNotePage(noteDto);
        }
        return ResultBean.success(pageInfo);
    }



    @ApiOperation(value = "获取所有点赞笔记")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getUpNotes")
    @OperLog(operModule = "获取所有点赞笔记",operType = OperType.QUERY,operDesc = "获取所有点赞笔记")
    public ResultBean<IPage<NoteVo>> getUpNotes() {
        String followId = String.valueOf(request.getAttribute("authorId"));
        NoteDto noteDto = new NoteDto();
        noteDto.setFollowId(followId);
        noteDto.setMyUpById(followId);
        IPage<NoteVo> pageInfo = noteService.selectNotePage(noteDto);
        return ResultBean.success(pageInfo);
    }


    @ApiOperation(value = "获取所有收藏笔记")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getStarNotes")
    @OperLog(operModule = "获取所有收藏笔记",operType = OperType.QUERY,operDesc = "获取所有收藏笔记")
    public ResultBean<IPage<NoteVo>> getStarNotes() {
        String followId = String.valueOf(request.getAttribute("authorId"));
        NoteDto noteDto = new NoteDto();
        noteDto.setFollowId(followId);
        noteDto.setMyStarById(followId);
        IPage<NoteVo> pageInfo = noteService.selectNotePage(noteDto);
        return ResultBean.success(pageInfo);
    }


    @ApiOperation(value = "获取博主信息")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getMine")
    @OperLog(operModule = "获取当前博主信息",operType = OperType.QUERY,operDesc = "获取当前博主信息")
    public ResultBean<Author> getMine() {
        String authorId = String.valueOf(request.getAttribute("authorId"));
        Author author = authorService.getById(authorId);
        return ResultBean.success(author);
    }


    @ApiOperation(value = "获取当前博主笔记")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getMineNotes")
    @OperLog(operModule = "获取当前博主笔记",operType = OperType.QUERY,operDesc = "获取当前博主笔记")
    public ResultBean<IPage<NoteVo>> getMineNotes() {
        String authorId = String.valueOf(request.getAttribute("authorId"));
        NoteDto noteDto = new NoteDto();
        noteDto.setFollowId(authorId);
        noteDto.setAuthorId(authorId);
        IPage<NoteVo> pageInfo = noteService.selectNotePage(noteDto);
        return ResultBean.success(pageInfo);
    }


    @ApiOperation(value = "点赞笔记")
    @ApiOperationSupport(order = 1)
    @PostMapping("/api/auth/upNote")
    @OperLog(operModule = "点赞笔记",operType = OperType.ADD,operDesc = "点赞笔记")
    public ResultBean upNote(@RequestBody NoteDto noteDto) {
        String followId = String.valueOf(request.getAttribute("authorId"));
        Author follow = authorService.getById(followId);
        Boolean isUp = Boolean.FALSE;
        //查看在不在点赞列表
        UpNotes upNotes = upNotesService.selectOneByFollowId(noteDto.getNoteId(), followId);
        //不在证明是点赞
        if(upNotes==null){
            upNotes = new UpNotes();
            upNotes.setAuthorId(noteDto.getAuthorId());
            upNotes.setAuthorName(noteDto.getAuthorName());
            upNotes.setFollowId(follow.getAuthorId());
            upNotes.setFollowName(follow.getAuthorName());
            upNotes.setNoteId(noteDto.getNoteId());
            upNotes.setNoteTitle(noteDto.getNoteTitle());
            isUp = Boolean.TRUE;
            upNotesService.save(upNotes);
        }else{
          //在则表示取消赞删除数据
            upNotesService.removeById(upNotes);
        }
        return ResultBean.success(isUp);
    };

    @ApiOperation(value = "收藏笔记")
    @ApiOperationSupport(order = 1)
    @PostMapping("/api/auth/starNote")
    @OperLog(operModule = "收藏笔记",operType = OperType.ADD,operDesc = "收藏笔记")
    public ResultBean starNote(@RequestBody NoteDto noteDto) {
        String followId = String.valueOf(request.getAttribute("authorId"));
        Author follow = authorService.getById(followId);
        Boolean isStar = Boolean.FALSE;
        //查看在不在点赞列表
        StarNotes starNotes = starNotesService.selectOneByFollowId(noteDto.getNoteId(), followId);
        //不在证明是点赞
        if(starNotes==null){
            starNotes = new StarNotes();
            starNotes.setAuthorId(noteDto.getAuthorId());
            starNotes.setAuthorName(noteDto.getAuthorName());
            starNotes.setFollowId(follow.getAuthorId());
            starNotes.setFollowName(follow.getAuthorName());
            starNotes.setNoteId(noteDto.getNoteId());
            starNotes.setNoteTitle(noteDto.getNoteTitle());
            isStar = Boolean.TRUE;
            starNotesService.save(starNotes);
        }else{
            //在则表示取消赞删除数据
            starNotesService.removeById(starNotes);
        }
        return ResultBean.success(isStar);
    };


    @ApiOperation(value = "创建笔记")
    @ApiOperationSupport(order = 1)
    @PostMapping("/api/auth/addNote")
    @OperLog(operModule = "创建笔记",operType = OperType.ADD,operDesc = "创建笔记")
    public ResultBean addNote(@RequestBody NoteDto noteDto) {
        String authorId = String.valueOf(request.getAttribute("authorId"));
        Author author = authorService.getById(authorId);

        Note note = BeanUtil.copyProperties(noteDto, Note.class);
        note.setAuthorId(author.getAuthorId());
        note.setAuthorName(author.getAuthorName());
        note.setAuthorAvatar(author.getAvatarUrl());
        note.setIpAddress(IPUtils.getIpAddr(request)); // 请求IP
        note.setIpRealAddress(AddressUtils.getRealAddress(note.getIpAddress()));
        noteService.save(note);

        List<String> imgs = noteDto.getImgs();
        List<NoteImg> noteImgList = new ArrayList<>();
        for(int i=0;i<imgs.size();i++){
            NoteImg noteImg = new NoteImg();
            noteImg.setAuthorId(authorId);
            noteImg.setNoteId(note.getNoteId());
            noteImg.setImgSort(i);
            File file = fileService.selectFileByFileId(imgs.get(i));
            String serverName = request.getServerName();
            System.out.println(serverName);
            noteImg.setImgUrl("http://" + serverName + ":" + port + file.getFilePath());
            noteImgList.add(noteImg);
        }
        noteImgService.saveBatch(noteImgList);

        Note updateNote = noteService.getById(note.getNoteId());
        updateNote.setFirstPicture(noteImgList.get(0).getImgUrl());
        noteService.updateById(updateNote);
        return ResultBean.success();
    }

    //外层倒叙 回复正序
    @ApiOperation(value = "获取笔记评论")
    @ApiOperationSupport(order = 1)
    @GetMapping("/api/auth/getNoteReply")
    @OperLog(operModule = "获取笔记评论",operType = OperType.QUERY,operDesc = "获取笔记评论")
    public ResultBean<Map> getNoteReply( ReplyDto replyDto) {
        String fellowId = String.valueOf(request.getAttribute("authorId"));


        String noteId = replyDto.getNoteId();
        List<ReplyVo> replyList = replyService.selectReplyList(new ReplyDto().setNoteId(noteId).setFollowId(fellowId));
        Integer totalCount = replyList.size();
        // 先构建一个以回复ID为键，回复对象为值的Map，方便后续快速查找回复对象
    // 构建以replyId为键，ReplyVo对象为值的Map，方便后续快速查找回复对象
        Map<String, ReplyVo> replyMap = replyList.stream()
                .collect(Collectors.toMap(ReplyVo::getReplyId, reply -> reply));

        List<ReplyVo> secondLevelReplies = replyList
        .stream()
        .filter(reply ->
                (StringUtil.isNotEmpty(reply.getParentId())||StringUtil.isNotEmpty(reply.getTopParentId()))
        ).sorted(Comparator.comparing(ReplyVo::getCreateTime)).collect(Collectors.toList());
        secondLevelReplies.forEach(replyVo -> {
            if(StringUtil.isNotEmpty(replyVo.getParentId())){
                replyVo.setParentAuthorId(replyMap.get(replyVo.getParentId()).getAuthorId());
                replyVo.setParentAuthorName(replyMap.get(replyVo.getParentId()).getAuthorName());
            }
        });

        // 获取第一层回复（topId为空且parentId也为空）
        List<ReplyVo> firstLevelReplies = replyList.stream()
                .filter(reply -> reply.getTopParentId() == null && reply.getParentId() == null)
                .collect(Collectors.toList());

        // 将第二层回复添加到对应的第一层回复下（通过topId与replyId关联）
        firstLevelReplies.forEach(firstLevelReply -> {
            String firstLevelReplyId = firstLevelReply.getReplyId();
            List<ReplyVo> relatedSecondLevelReplies = secondLevelReplies.stream()
                    .filter(secondLevelReply -> firstLevelReplyId.equals(secondLevelReply.getTopParentId()))
                    .collect(Collectors.toList());
            if (firstLevelReply.getReply() == null) {
                firstLevelReply.setReply(new ArrayList<>());
            }
            firstLevelReply.getReply().addAll(relatedSecondLevelReplies);
        });


        Map map = new HashMap();
        map.put("totalCount",totalCount);
        map.put("replys",firstLevelReplies);


        return ResultBean.success(map);
    }


//        // 先按照parentId进行分组，用于后续查找子回复
//        Map<String, List<ReplyVo>> groupedByParentId = replyList.stream()
//                .filter(reply -> reply.getParentId()!= null &&!reply.getParentId().isEmpty())
//                .collect(Collectors.groupingBy(ReplyVo::getParentId));
//
//        // 处理每一个顶级回复（parentId为null的回复），递归构建树形结构
//        List<ReplyVo> resultList = replyList.stream()
//                .filter(reply -> reply.getParentId() == null || reply.getParentId().isEmpty())
//                .peek(parentReply -> {
//                    // 递归设置子回复列表
//                    setChildrenReplies(parentReply, groupedByParentId);
//                })
//                .collect(Collectors.toList());

//        // 第一步：将回复列表按照parentId进行分组，key是parentId，value是对应的回复列表
//        Map<String, List<ReplyVo>> groupedByParentId = replyList.stream()
//                .filter(reply -> reply.getParentId()!= null &&!reply.getParentId().isEmpty())
//                .collect(Collectors.groupingBy(ReplyVo::getParentId));
//
//        // 第二步：创建一个新的列表，用于存放最终处理后的回复列表，先将没有parentId的元素添加进去
//        List<ReplyVo> resultList = replyList.stream()
//                .filter(reply -> reply.getParentId() == null || reply.getParentId().isEmpty())
//                .collect(Collectors.toList());
//
//        // 第三步：遍历没有parentId的元素，将其对应的子回复列表（通过parentId从分组中获取）设置到Reply属性下
//        resultList.forEach(parentReply -> {
//            String parentId = parentReply.getReplyId();
//            List<ReplyVo> childrenReplies = groupedByParentId.getOrDefault(parentId, new ArrayList<>());
//            parentReply.setReply(childrenReplies);
//        });

        //不再无限极调用 因为前端页面我不会写。。。 采用和官方一样的@形式


    private static void setChildrenReplies(ReplyVo parentReply, Map<String, List<ReplyVo>> groupedByParentId) {
        String parentId = parentReply.getReplyId();
        List<ReplyVo> childrenReplies = groupedByParentId.getOrDefault(parentId, new ArrayList<>());
        // 遍历当前层级的子回复，递归设置它们的子回复
        childrenReplies.forEach(childReply -> {
            setChildrenReplies(childReply, groupedByParentId);
        });
        parentReply.setReply(childrenReplies);
    }

    @ApiOperation(value = "回复笔记")
    @ApiOperationSupport(order = 1)
    @PostMapping("/api/auth/replyNote")
    @OperLog(operModule = "回复笔记",operType = OperType.ADD,operDesc = "回复笔记")
    public ResultBean replyNote(@RequestBody ReplyDto replyDto) {
        String authorId = String.valueOf(request.getAttribute("authorId"));
        Author author = authorService.getById(authorId);
        Note note = noteService.getById(replyDto.getNoteId());
        if (authorId.equals(note.getAuthorId())) {
            replyDto.setAuthorReplay(TRUE);
        }

        List<ReplyVo> replyList = replyService.selectReplyList(new ReplyDto().setNoteId(replyDto.getNoteId()));
        if (CollectionUtil.isEmpty(replyList)) {
            replyDto.setFirstReplay(TRUE);
        }
        replyDto.setNoteId(note.getNoteId());
        replyDto.setNoteTitle(note.getNoteTitle());
        replyDto.setAuthorId(authorId);
        replyDto.setAuthorName(author.getAuthorName());
        replyDto.setAvatarUrl(author.getAvatarUrl());
        replyDto.setIpAddress(IPUtils.getIpAddr(request)); // 请求IP
        replyDto.setIpRealAddress(AddressUtils.getRealAddress(replyDto.getIpAddress()));
        Reply reply = BeanUtil.copyProperties(replyDto, Reply.class);
        replyService.save(reply);
        return ResultBean.success();
    }


    @ApiOperation(value = "点赞评论")
    @ApiOperationSupport(order = 1)
    @PostMapping("/api/auth/upReply")
    @OperLog(operModule = "点赞评论",operType = OperType.ADD,operDesc = "点赞评论")
    public ResultBean upReply(@RequestBody ReplyDto replyDto) {
        String followId = String.valueOf(request.getAttribute("authorId"));
        Author follow = authorService.getById(followId);
        Boolean isUp = Boolean.FALSE;
        //查看在不在点赞列表
        UpReplys upReplys = upReplysService.selectOneByFollowId(replyDto.getReplyId(), followId);
        //不在证明是点赞
        if(upReplys==null){
            upReplys = new UpReplys();
            upReplys.setAuthorId(replyDto.getAuthorId());
            upReplys.setAuthorName(replyDto.getAuthorName());
            upReplys.setFollowId(follow.getAuthorId());
            upReplys.setFollowName(follow.getAuthorName());
            upReplys.setReplyId(replyDto.getReplyId());
            upReplys.setReplyContent(replyDto.getReplayContent());
            isUp = Boolean.TRUE;
            upReplysService.save(upReplys);
        }else{
            //在则表示取消赞删除数据
            upReplysService.removeById(upReplys);
        }
        return ResultBean.success(isUp);
    };

}
